package com.streambolics.std;

/**
 * A parser using the Simple Access for Ini Notation.
 * 
 * SAIN is a simple way of parsing INI formatted files or streams. SAIN is the
 * acronym for Simple Access for INI Notation. It is meant as a simple protocol
 * to parse a stream formatted somewhat like a Windows INI file.
 * 
 * The SAIN protocol recognizes the INI notation as being made of text lines,
 * some of which are section names, some of which are ignored (comments) and all
 * others are values within a section.
 * 
 * 
 * @author Sauron
 * 
 */

public abstract class SainParser extends LineParser
{
    private String _CurSection;

    /**
     * Adds a name/value pair to a section.
     * 
     * This is a special case of the addValue method.
     * 
     * @param aSectionName
     *            The name of the section to which the value pair must be added.
     * @param aName
     *            The name of the value
     * @param aValue
     *            The actual value.
     * @throws Exception
     *             Standard Streambolics behaviour for exceptions.
     */

    protected abstract void addMapping (String aSectionName, String aName, String aValue) throws Exception;

    /**
     * Adds a value to a section.
     * 
     * An implementation should redefine this to add the value to the section.
     * It is guaranteed that beginSection has been called before, and that
     * endSection will be called afterwards, even if this method throws an
     * exception.
     * 
     * @param aSectionName
     *            The name of the section where the value is to be added.
     * @param aValue
     *            The value to add.
     * @throws Exception
     *             Standard Streambolics behaviour for exceptions.
     */

    protected void addValue (String aSectionName, String aValue) throws Exception
    {
        addMapping (aSectionName, StringExtensions.before (aValue, "="), StringExtensions.after (aValue, "="));
    }

    protected abstract void beginSection (String aSectionName) throws Exception;

    @Override
    protected void beginVisit () throws Exception
    {
        super.beginVisit ();
        flushSection ();
    }

    protected abstract void endSection (String aSectionName) throws Exception;

    @Override
    protected final void endVisit () throws Exception
    {
        flushSection ();
        super.endVisit ();
    }

    private void flushSection () throws Exception
    {
        if (_CurSection != null)
        {
            endSection (_CurSection);
            _CurSection = null;
        }
    }

    @Override
    protected final void visit (String s) throws Exception
    {
        if (s == null)
        {
            return;
        }
        s = s.trim ();
        if (s.startsWith (";"))
        {
            return;
        }
        if (s.startsWith ("["))
        {
            flushSection ();
            beginSection (StringExtensions.between (s, "[", "]"));
        }
        else if (_CurSection != null)
        {
            addValue (_CurSection, s);
        }

    }
}
